﻿using System;

// XNA lib
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Media;

//Oak Engine Lib
using OakEngine.GameState;
using OakEngine.Input;
using Microsoft.Xna.Framework.Input;

namespace MainJumpFleet.GameStates
{
   public class MainGameScreenState : OAK_IGameState
    {
        #region OAK_IGameState Members
        SpriteBatch batch;
        SpriteFont mainMenuFont;

        // holds the SpriteManager object
        private JumpFleetGameLib.xSprite.SpriteManager spriteManager;
              
       // holds the background music and sound effects        
        private Song backgroundMusicSong;
        private SoundEffect explosionSoundEffect;
        private SoundEffect laserSoundEffect;
        private SoundEffect missileSoundEffect;

        // holds the textures
        private Texture2D starfieldBackgroundTexture;
        private Texture2D playerShipTexture;
        private Texture2D[] asteroidTextures;
        private Texture2D[] planetTextures;
        private Texture2D missileTexture;
        private Texture2D laserTexture;        

        // holds the sector map 
        private JumpFleetGameLib.xMap.SectorMap.SectorMap alpha1SectorMap;

        // holds the PlayerShip object
        private PlayerShip.PlayerShip playerShip;
        

        public MainGameScreenState()
        {
            Enter();
        }


        public void Enter()
        {
            mainMenuFont = CGame.CGame.GetInstance().Content.Load<SpriteFont>("Fonts\\mainMenuFont");
            batch = CGame.CGame.GetInstance().SpriteBatch;

            // creates the SpriteManager object
            spriteManager = new JumpFleetGameLib.xSprite.SpriteManager();

            #region LOAD AUDIO
            // loads the background music
            backgroundMusicSong = CGame.CGame.GetInstance().Content.Load<Song>(@"backgroundMusic\beacon_of_hope_strings");

            // loads the sound effects
            explosionSoundEffect = CGame.CGame.GetInstance().Content.Load<SoundEffect>(@"soundEffects\bomb");
            laserSoundEffect = CGame.CGame.GetInstance().Content.Load<SoundEffect>(@"soundEffects\laser");
            missileSoundEffect = CGame.CGame.GetInstance().Content.Load<SoundEffect>(@"soundEffects\missilelaunch");
            #endregion

            #region LOAD TEXTURES
            // loads the textures
            starfieldBackgroundTexture = CGame.CGame.GetInstance().Content.Load<Texture2D>(@"textures\starfield_1024x1024");
            playerShipTexture = CGame.CGame.GetInstance().Content.Load<Texture2D>(@"textures\ship2_77x128");
            missileTexture = CGame.CGame.GetInstance().Content.Load<Texture2D>(@"textures\missile_6x14");
            laserTexture = CGame.CGame.GetInstance().Content.Load<Texture2D>(@"textures\laser_untinted_10x21");
            

            asteroidTextures = new Texture2D[10];
            asteroidTextures[0] = CGame.CGame.GetInstance().Content.Load<Texture2D>(@"textures\asteroid01_untinted_126x128");
            asteroidTextures[1] = CGame.CGame.GetInstance().Content.Load<Texture2D>(@"textures\asteroid02_untinted_102x128");
            asteroidTextures[2] = CGame.CGame.GetInstance().Content.Load<Texture2D>(@"textures\asteroid03_untinted_101x128");
            asteroidTextures[3] = CGame.CGame.GetInstance().Content.Load<Texture2D>(@"textures\asteroid04_untinted_111x128");
            asteroidTextures[4] = CGame.CGame.GetInstance().Content.Load<Texture2D>(@"textures\asteroid05_untinted_128x115");
            asteroidTextures[5] = CGame.CGame.GetInstance().Content.Load<Texture2D>(@"textures\asteroid06_untinted_128x104");
            asteroidTextures[6] = CGame.CGame.GetInstance().Content.Load<Texture2D>(@"textures\asteroid07_untinted_128x109");
            asteroidTextures[7] = CGame.CGame.GetInstance().Content.Load<Texture2D>(@"textures\asteroid08_untinted_127x128");
            asteroidTextures[8] = CGame.CGame.GetInstance().Content.Load<Texture2D>(@"textures\asteroid09_untinted_111x128");

            planetTextures = new Texture2D[3];
            planetTextures[0] = CGame.CGame.GetInstance().Content.Load<Texture2D>(@"textures\planet08_512x512");
            planetTextures[1] = CGame.CGame.GetInstance().Content.Load<Texture2D>(@"textures\planet10_512x512");
            planetTextures[2] = CGame.CGame.GetInstance().Content.Load<Texture2D>(@"textures\planet12_512x512");
            #endregion

            #region LOAD SPRITE TEMPLATES
            // creates the static sprite template for the starfield background 
            spriteManager.CreateStaticSpriteTemplate("StarfieldBackground", starfieldBackgroundTexture, 0, 0, 1024, 1024, Color.White, 255, 0, JumpFleetGameLib.xSprite.RotationAnchorPoint.TopLeft, 1.0f, SpriteEffects.None, 1.0f);

            // creates the static sprite template for the player ship
            spriteManager.CreateStaticSpriteTemplate("PlayerShip", playerShipTexture, 0, 0, 77, 128, Color.White, 255, 0, JumpFleetGameLib.xSprite.RotationAnchorPoint.Center, 1.0f, SpriteEffects.None, 0.3f);

            // creates the static sprite template for the missile
            spriteManager.CreateStaticSpriteTemplate("Missile", missileTexture, 0, 0, 6, 14, Color.White, 255, 0, JumpFleetGameLib.xSprite.RotationAnchorPoint.Center, 1.5f, SpriteEffects.None, 0.301f);

            // creates the static sprite template for the lasers
            spriteManager.CreateStaticSpriteTemplate("BlueLaser", laserTexture, 0, 0, 4, 16, new Color(149, 138, 255), 255, 0, JumpFleetGameLib.xSprite.RotationAnchorPoint.Center, 1.0f, SpriteEffects.None, 0.301f);
            spriteManager.CreateStaticSpriteTemplate("RedLaser", laserTexture, 0, 0, 4, 16, Color.Red, 255, 0, JumpFleetGameLib.xSprite.RotationAnchorPoint.Center, 1.0f, SpriteEffects.None, 0.301f);

            // sets the color for the asteroid
            Color asteroid1Color = new Color(184, 138, 64);

            // creates the static sprite templates for the asteroids
            spriteManager.CreateStaticSpriteTemplate("LargeAsteroid1", asteroidTextures[0], 0, 0, 126, 128, asteroid1Color, 255, 0, JumpFleetGameLib.xSprite.RotationAnchorPoint.Center, 1.0f, SpriteEffects.None, 0.5f);
            spriteManager.CreateStaticSpriteTemplate("LargeAsteroid2", asteroidTextures[1], 0, 0, 102, 128, asteroid1Color, 255, 0, JumpFleetGameLib.xSprite.RotationAnchorPoint.Center, 1.0f, SpriteEffects.None, 0.5f);
            spriteManager.CreateStaticSpriteTemplate("LargeAsteroid3", asteroidTextures[2], 0, 0, 101, 128, asteroid1Color, 255, 0, JumpFleetGameLib.xSprite.RotationAnchorPoint.Center, 1.0f, SpriteEffects.None, 0.5f);
            spriteManager.CreateStaticSpriteTemplate("LargeAsteroid4", asteroidTextures[3], 0, 0, 111, 128, asteroid1Color, 255, 0, JumpFleetGameLib.xSprite.RotationAnchorPoint.Center, 1.0f, SpriteEffects.None, 0.5f);

            // creates the static sprite templates for the planets
            spriteManager.CreateStaticSpriteTemplate("LargePlanet1", planetTextures[0], 0, 0, 512, 512, Color.White, 255, 0, JumpFleetGameLib.xSprite.RotationAnchorPoint.Center, 1.0f, SpriteEffects.None, 0.6f);
            spriteManager.CreateStaticSpriteTemplate("MediumPlanet1", planetTextures[1], 0, 0, 512, 512, Color.White, 255, 0, JumpFleetGameLib.xSprite.RotationAnchorPoint.Center, 0.85f, SpriteEffects.None, 0.6f);
            spriteManager.CreateStaticSpriteTemplate("SmallPlanet1", planetTextures[2], 0, 0, 512, 512, Color.White, 255, 0, JumpFleetGameLib.xSprite.RotationAnchorPoint.Center, 0.7f, SpriteEffects.None, 0.6f);
            #endregion

            #region LOAD SECTOR MAP
            alpha1SectorMap = new JumpFleetGameLib.xMap.SectorMap.SectorMap("Alpha1", 1, 2, 1024, 1024, 3, 3);

            // sets the background layer's tag
            alpha1SectorMap.BackgroundLayers[0].Tag = "StarfieldBackground";

            // sets the asteroid object layer's tag
            alpha1SectorMap.ObjectLayers[0].Tag = "Asteroids";

            // sets the planet object layer's tag
            alpha1SectorMap.ObjectLayers[1].Tag = "Planets";

            // sets up a starfield background tile to clone
            JumpFleetGameLib.xMap.SectorMap.StaticBackgroundTile starfieldBackgroundTile = new JumpFleetGameLib.xMap.SectorMap.StaticBackgroundTile(spriteManager, "StarfieldBackground", "StarfieldBackground", 1024, 1024, 1.0f);

            // fills the sector map with starfield background tiles
            for (int row = 0; row < alpha1SectorMap.BackgroundLayers[0].Tiles.GetLength(1); row++)
                for (int column = 0; column < alpha1SectorMap.BackgroundLayers[0].Tiles.GetLength(0); column++)
                {
                    alpha1SectorMap.BackgroundLayers[0].Tiles[column, row] = starfieldBackgroundTile.Clone();
                    alpha1SectorMap.BackgroundLayers[0].Tiles[column, row].Position = new Vector2(column * starfieldBackgroundTile.Width, row * starfieldBackgroundTile.Height);
                }

            // sets up the asteroids            
            alpha1SectorMap.ObjectLayers[0].PositionableObjectList.Add(new Asteroid.Asteroid(spriteManager.CreateNewStaticSpriteFromTemplate("LargeAsteroid1"), 0.1f, true));
            alpha1SectorMap.ObjectLayers[0].PositionableObjectList[0].CurrentMapOffset = new Vector2(512, 100);
            alpha1SectorMap.ObjectLayers[0].PositionableObjectList.Add(new Asteroid.Asteroid(spriteManager.CreateNewStaticSpriteFromTemplate("LargeAsteroid2"), 0.15f, false));
            alpha1SectorMap.ObjectLayers[0].PositionableObjectList[1].CurrentMapOffset = new Vector2(2700, 600);
            alpha1SectorMap.ObjectLayers[0].PositionableObjectList.Add(new Asteroid.Asteroid(spriteManager.CreateNewStaticSpriteFromTemplate("LargeAsteroid2"), 0.13f, true));
            alpha1SectorMap.ObjectLayers[0].PositionableObjectList[2].CurrentMapOffset = new Vector2(460, 1650);
            alpha1SectorMap.ObjectLayers[0].PositionableObjectList.Add(new Asteroid.Asteroid(spriteManager.CreateNewStaticSpriteFromTemplate("LargeAsteroid3"), 0.16f, false));
            alpha1SectorMap.ObjectLayers[0].PositionableObjectList[3].CurrentMapOffset = new Vector2(1658, 1719);

            // sets up the planets
            alpha1SectorMap.ObjectLayers[1].PositionableObjectList.Add(new Planet.Planet(spriteManager.CreateNewStaticSpriteFromTemplate("LargePlanet1")));
            alpha1SectorMap.ObjectLayers[1].PositionableObjectList[0].CurrentMapOffset = new Vector2(1072, 532);
            alpha1SectorMap.ObjectLayers[1].PositionableObjectList.Add(new Planet.Planet(spriteManager.CreateNewStaticSpriteFromTemplate("MediumPlanet1")));
            alpha1SectorMap.ObjectLayers[1].PositionableObjectList[1].CurrentMapOffset = new Vector2(752, 2618);
            alpha1SectorMap.ObjectLayers[1].PositionableObjectList.Add(new Planet.Planet(spriteManager.CreateNewStaticSpriteFromTemplate("SmallPlanet1")));
            alpha1SectorMap.ObjectLayers[1].PositionableObjectList[2].CurrentMapOffset = new Vector2(2390, 2377);

            // sets the drawing depth for the background layer
            alpha1SectorMap.BackgroundLayers[0].Depth = 0.999f;

            // sets the background layer to visible
            alpha1SectorMap.BackgroundLayers[0].Visible = true;

            // sets the asteroid object layer's depth and visible
            alpha1SectorMap.ObjectLayers[0].Depth = 0.5f;
            alpha1SectorMap.ObjectLayers[0].Visible = true;

            // sets the planet object layer's depth and visible
            alpha1SectorMap.ObjectLayers[1].Depth = 0.6f;
            alpha1SectorMap.ObjectLayers[1].Visible = true;

            // sets the starting position for the sector map
            alpha1SectorMap.CurrentStartingDrawPosition = new Vector2(0, 0);

            #endregion

            #region PLAYER SHIP
            playerShip = new PlayerShip.PlayerShip(spriteManager.CreateNewStaticSpriteFromTemplate("PlayerShip"), 150.0f);
            playerShip.CurrentPosition = new Vector2(100, 100);
            playerShip.RotationAngle = MathHelper.ToRadians(90);
            playerShip.Visible = true;
            playerShip.Camera = new JumpFleetGameLib.xCamera.Camera2D(CGame.CGame.GetInstance().Device.Viewport.Width, CGame.CGame.GetInstance().Device.Viewport.Height, playerShip, alpha1SectorMap);
            #endregion      
         
            // starts playing the background music            
            MediaPlayer.Play(backgroundMusicSong);
            MediaPlayer.IsRepeating = true;            
        }

        public bool Input(OAK_InputManager input)
        {
            if (input.Pressed(Keys.Escape) || input.Pressed(Buttons.Back, 0))
                CGame.CGame.GetInstance().ChangeState(new MainMenuState());

            if (CGame.CGame.GetInstance().Input.GamePads[0].Buttons.X == ButtonState.Pressed)
                explosionSoundEffect.Play();

            if (CGame.CGame.GetInstance().Input.GamePads[0].Buttons.Y == ButtonState.Pressed)
                laserSoundEffect.Play();

            if (CGame.CGame.GetInstance().Input.GamePads[0].Buttons.B == ButtonState.Pressed)
                missileSoundEffect.Play();


            return false;
        }

        public void Update(GameTime dt)
        {
            // sends the GamePadState to the player ship object
            playerShip.Update(dt, CGame.CGame.GetInstance().Input.GamePads[0]);

            // updates the map objects
            alpha1SectorMap.UpdateObjects(dt);
        }

        public void Render()
        {
            // batch.DrawString(mainMenuFont, "Welcome to Main Game Screen State\n Press Esc to go back to Main menu ", new Vector2(300, 250), Color.White);

            // ends the SpriteBatch from CGame
            batch.End();

            // starts the local SpriteBatch
            batch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);

            // let the SpriteManager do it's job
            spriteManager.Draw(batch);

            // ends the local SpriteBatch
            batch.End();

            // starts the SpriteBatch again so I don't break the other GameStates
            batch.Begin();

        }

        

        public void Exit()
        {
            MediaPlayer.Stop();
        }

        #endregion
    }
}
